#include "StdAfx.h"
#include "M2Info.h"

M2Info::M2Info(const std::string& modName) : mFile(modName) {
	if(!mFile.IsOpened())
		throw std::exception("File not found!");

	
	mHeader = mFile.ReadInc<M2Header>();
	mFile.SetInc(mHeader.ofsName);
	std::vector<char> name(mHeader.lenName);
	mFile.ReadInc(name.size(), &name[0]);
	mModelName = &name[0];

	std::string::size_type t = modName.rfind('\\');
	if(t != std::string::npos) {
		mFileDirectory = modName.substr(0, t);
	} else
		mFileDirectory = modName;

	ParseVertices();
	LoadTextures();
	LoadSkins();
}

void M2Info::LoadSkins() {
	std::string skinFile = mFileDirectory;
	skinFile += "\\";
	skinFile += mModelName + "00.skin";

	CMpqFile skin(skinFile);
	if(!skin.IsOpened())
		throw std::exception("Missing SKIN");

	SKINView mView = skin.ReadInc<SKINView>();
	ui16* indexLookup = new ui16[mView.nIndices];
	skin.SetInc(mView.ofsIndices);
	skin.ReadInc(mView.nIndices * 2, indexLookup);

	ui16* triangles = new ui16[mView.nTriangles];
	skin.SetInc(mView.ofsTriangles);
	skin.ReadInc(mView.nTriangles * 2, triangles);

	SKINSubMesh* SubMeshes = new SKINSubMesh[mView.nSubMeshes];
	skin.Read(mView.ofsSubMeshes, mView.nSubMeshes * sizeof(SKINSubMesh), SubMeshes);

	SKINTexUnit* TexUnits = new SKINTexUnit[mView.nTexUnits];
	skin.Read(mView.ofsTexUnits, mView.nTexUnits * sizeof(SKINTexUnit), TexUnits);

	ui16* texLookup = new ui16[mHeader.nTexLookups];
	mFile.Read(mHeader.ofsTexLookups, mHeader.nTexLookups * 2, texLookup);

	ui16* texUnitLookUp = new ui16[mHeader.nTexUnits];
	mFile.Read(mHeader.ofsTexUnits, 2 * mHeader.nTexUnits, texUnitLookUp);

	mIndices = new ui16[mView.nTriangles];
	nIndices = mView.nTriangles;
	for(ui32 i = 0; i < mView.nTriangles; ++i)
		mIndices[i] = indexLookup[triangles[i]];

	for(ui32 i = 0; i < mView.nTexUnits; ++i) {
		SKINSubMesh& mesh = SubMeshes[TexUnits[i].SubMesh1];
		M2RenderPass pass;
		pass.Texture = mTextureNames[texLookup[TexUnits[i].Texture]];
		pass.nIndices = mesh.nTriangles;
		pass.startIndex = mesh.startTriangle;

		/*for(ui16 t = mesh.startTriangle, k = 0; k < mesh.nTriangles; ++t, ++k) {
			ui16 index = indices[t];
			pass.Vertices.push_back(mModelVertices[index]);
		}*/

		mPasses.push_back(pass);
	}

	delete [] texUnitLookUp;
	delete [] texLookup;
	delete [] TexUnits;
	delete [] SubMeshes;
	delete [] triangles;
	delete [] indexLookup;
}

void M2Info::ParseVertices() {
	mVertices.resize(mHeader.nVertices);
	mModelVertices.resize(mHeader.nVertices);
	ui32 counter = 0;
	mFile.Read(mHeader.ofsVertices, mHeader.nVertices * sizeof(M2Vertex), &mVertices[0]);
	std::for_each(mVertices.begin(), mVertices.end(),
		[this, &counter](M2Vertex& v) {
			MdxVertex mv = {
				v.x,
				v.y,
				v.z,
				v.nx,
				v.ny,
				v.nz,
				v.u,
				v.v
			};

			mModelVertices[counter++] = mv;
	}
	);
}

void M2Info::LoadTextures() {
	mTextures.resize(mHeader.nTextures);
	mTextureNames.resize(mHeader.nTextures);
	ui32 counter = 0;
	mFile.Read(mHeader.ofsTextures, mHeader.nTextures * sizeof(M2Texture), &mTextures[0]);
	std::for_each(mTextures.begin(), mTextures.end(),
		[this, &counter](M2Texture& tex) {
		std::vector<char> data(tex.lenName);
		mFile.Read(tex.ofsName, tex.lenName, &data[0]);
		mTextureNames[counter++] = &data[0];
	}
	);
}